package com.mmm.order.service.impl;

import com.alibaba.fastjson.JSON;
import com.mmm.common.utils.EsPage;
import com.mmm.common.vo.Paging;
import com.mmm.common.vo.SuccessVo;
import com.mmm.feign.client.DeliveryClient;
import com.mmm.feign.client.UserClient;
import com.mmm.order.entity.Express;
import com.mmm.order.dao.ExpressDao;
import com.mmm.order.service.ExpressService;
import com.mmm.user.entity.Delivery;
import com.mmm.user.entity.User;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import static com.mmm.order.variable.ExpressEsVariable.ORDER_NAME;
import static com.mmm.order.variable.ExpressMQVaribale.*;

/**
 * (Express)表服务实现类
 *
 * @author One
 * @since 2022-03-05 21:09:37
 */
@Service("expressService")
@Transactional
public class ExpressServiceImpl implements ExpressService {
    @Resource
    private ExpressDao expressDao;

    @Autowired
    private UserClient userClient;
    @Autowired
    private DeliveryClient deliveryClient;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private RestHighLevelClient client;

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public Express queryById(Long id) {
        return this.expressDao.queryById(id);
    }

    /**
     * 查询多条数据
     *
     * @param offset 查询起始位置
     * @param limit  查询条数
     * @return 对象列表
     */
    @Override
    public List<Express> queryAllByLimit(int offset, int limit) {
        return this.expressDao.queryAllByLimit(offset, limit);
    }

    /**
     * 新增数据
     *
     * @param express 实例对象
     * @return 实例对象
     */
    @Override
    public Express insert(HttpServletRequest request, Express express) {
        String authorization = request.getHeader("Authorization");
        Map<String, String> claim = userClient.getClaim(authorization);
        int uid = Integer.parseInt(claim.get("uid"));
        SuccessVo<User> userSuccessVo = this.userClient.selectOne(Long.parseLong(uid + ""));
        User user = userSuccessVo.getData();
        express.setAvatar(user.getAvatar());
        express.setPhone(user.getPhone());
        express.setUName(user.getNickName());
        Date date = new Date();
        express.setUid(uid);
        express.setCreateTime(date);
        express.setUpdateTime(date);
        this.expressDao.insert(express);
        rabbitTemplate.convertAndSend(EXPRESS_EXCHANGE, EXPRESS_INSERT_KEY, express.getId());
        return express;
    }

    /**
     * 修改数据
     *
     * @param express 实例对象
     * @return 实例对象
     */
    @Override
    public Express update(Express express) {
        express.setUpdateTime(new Date());
        this.expressDao.update(express);
        rabbitTemplate.convertAndSend(EXPRESS_EXCHANGE, EXPRESS_INSERT_KEY, express.getId());
        return this.queryById(express.getId());
    }

    @Override
    public Express addOrder(String authorization, Express express) {
        Map<String, String> claim = userClient.getClaim(authorization);
        String uid = claim.get("uid");
        express.setRecUid(Integer.parseInt(uid));
        express.setUpdateTime(new Date());
        this.expressDao.update(express);
        rabbitTemplate.convertAndSend(EXPRESS_EXCHANGE, EXPRESS_INSERT_KEY, express.getId());
        return this.queryById(express.getId());
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(Long id) {
        Express express = this.expressDao.queryById(id);
        express.setDeleteTime(new Date());
        int update = this.expressDao.update(express);
        rabbitTemplate.convertAndSend(EXPRESS_EXCHANGE, EXPRESS_DELETE_KEY, express.getId());
        return update > 0;
    }

    @Override
    public Express findById(Long id) {
        GetRequest request = new GetRequest(ORDER_NAME);
        request.id(id.toString());
        try {
            GetResponse response = this.client.get(request, RequestOptions.DEFAULT);
            String source = response.getSourceAsString();
            return JSON.parseObject(source, Express.class);
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("express 查找失败");
        }
    }

    @Override
    public Paging<Express> list(Integer page, Integer size) {
        try {
            SearchRequest request = new SearchRequest(ORDER_NAME);
            BoolQueryBuilder bool = QueryBuilders.boolQuery();
            request.source().query(bool).sort("updateTime", SortOrder.DESC).size(size).from(page);
            SearchResponse search = client.search(request, RequestOptions.DEFAULT);
            Paging<Express> expressPaging = EsPage.simplePage(Express.class, search, page, size);
            for (Express item : expressPaging.getItems()) {
                SuccessVo<User> userSuccessVo = userClient.selectOne(Long.parseLong(item.getUid() + ""));
                if (userSuccessVo.getData() != null) {
                    item.setAvatar(userSuccessVo.getData().getAvatar());
                }
            }
            return expressPaging;
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("express 分页查询失败");
        }
    }

    @Override
    public void insertQueueOrUpdate(Long id) {
        try {
            Express express = this.queryById(id);
            DeleteRequest deleteRequest = new DeleteRequest(ORDER_NAME, id.toString());
            this.client.delete(deleteRequest, RequestOptions.DEFAULT);
            IndexRequest request = new IndexRequest(ORDER_NAME).id(id.toString());
            request.source(JSON.toJSONString(express), XContentType.JSON);
            this.client.index(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    @Override
    public void deleteQueue(Long id) {
        try {
            DeleteRequest request = new DeleteRequest(ORDER_NAME, id.toString());
            this.client.delete(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    @Override
    public Paging<Express> getMyExpressAll(String token, Integer page, Integer size) {
        Map<String, String> claim = userClient.getClaim(token);
        String uid = claim.get("uid");
        try {
            SearchRequest request = new SearchRequest(ORDER_NAME);
            BoolQueryBuilder bool = QueryBuilders.boolQuery();
            bool.must(QueryBuilders.termQuery("uid", uid));
            request.source().query(bool).sort("updateTime", SortOrder.DESC).from(page).size(size);
            SearchResponse search = this.client.search(request, RequestOptions.DEFAULT);
            return EsPage.simplePage(Express.class, search, page, size);
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("我的express all 查询失败");
        }

    }

    @Override
    public Paging<Express> getMyExpressUnfinished(String token, Integer page, Integer size) {
        Map<String, String> claim = userClient.getClaim(token);
        String uid = claim.get("uid");

        try {
            SearchRequest request = new SearchRequest(ORDER_NAME);
            BoolQueryBuilder bool = QueryBuilders.boolQuery();
            bool.must(QueryBuilders.termQuery("uid", uid)).filter(QueryBuilders.termQuery("status", 0));
            request.source().query(bool).size(size).from(page).sort("updateTime", SortOrder.DESC);
            SearchResponse search = this.client.search(request, RequestOptions.DEFAULT);
            return EsPage.simplePage(Express.class, search, page, size);
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("我的express unfinished查询失败");
        }
    }

    @Override
    public Paging<Express> getMyExpressFinish(String token, Integer page, Integer size) {
        Map<String, String> claim = userClient.getClaim(token);
        String uid = claim.get("uid");

        try {
            SearchRequest request = new SearchRequest(ORDER_NAME);
            BoolQueryBuilder bool = QueryBuilders.boolQuery();
            bool.must(QueryBuilders.termQuery("uid", uid)).filter(QueryBuilders.termQuery("status", 1));
            request.source().query(bool).size(size).from(page).sort("updateTime", SortOrder.DESC);
            SearchResponse search = this.client.search(request, RequestOptions.DEFAULT);
            return EsPage.simplePage(Express.class, search, page, size);
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("我的express finished查询失败");
        }
    }

    @Override
    public Paging<Express> getTaskUnfinished(String token, Integer page, Integer size) {
        Map<String, String> claim = userClient.getClaim(token);
        String uid = claim.get("uid");
        try {
            SearchRequest request = new SearchRequest(ORDER_NAME);
            BoolQueryBuilder bool = QueryBuilders.boolQuery();
            bool.must(QueryBuilders.termQuery("recUid", uid)).filter(QueryBuilders.termQuery("status", "0"));
            request.source().query(bool).sort("updateTime", SortOrder.DESC).size(size).from(page);
            SearchResponse search = client.search(request, RequestOptions.DEFAULT);
            return EsPage.simplePage(Express.class, search, page, size);
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("我的express finished查询失败");
        }
    }

    @Override
    public Paging<Express> getTaskFinished(String token, Integer page, Integer size) {
        Map<String, String> claim = userClient.getClaim(token);
        String uid = claim.get("uid");
        try {
            SearchRequest request = new SearchRequest(ORDER_NAME);
            BoolQueryBuilder bool = QueryBuilders.boolQuery();
            bool.must(QueryBuilders.termQuery("recUid", uid)).filter(QueryBuilders.termQuery("status", 1));
            request.source().query(bool).sort("updateTime", SortOrder.DESC).size(size).from(page);
            SearchResponse search = client.search(request, RequestOptions.DEFAULT);
            return EsPage.simplePage(Express.class, search, page, size);
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("我的express finished查询失败");
        }
    }

    @Override
    public Paging<Express> getTaskAll(String token, Integer page, Integer size) {
        Map<String, String> claim = userClient.getClaim(token);
        String uid = claim.get("uid");
        try {
            SearchRequest request = new SearchRequest(ORDER_NAME);
            BoolQueryBuilder bool = QueryBuilders.boolQuery();
            bool.must(QueryBuilders.termQuery("recUid", uid));
            request.source().query(bool).sort("updateTime", SortOrder.DESC).size(size).from(page);
            SearchResponse search = client.search(request, RequestOptions.DEFAULT);
            return EsPage.simplePage(Express.class, search, page, size);
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("我的express finished查询失败");
        }
    }

    @Override
    public Paging<Express> byDeliveryId(Integer id, Integer page, Integer size) {

        try {
            SearchRequest request = new SearchRequest(ORDER_NAME);
            BoolQueryBuilder bool = QueryBuilders.boolQuery();
            bool.must(QueryBuilders.termQuery("deliveryId", id));
            request.source().query(bool).sort("updateTime", SortOrder.DESC).size(size).from(page);
            SearchResponse search = client.search(request, RequestOptions.DEFAULT);
            Paging<Express> expressPaging = EsPage.simplePage(Express.class, search, page, size);
            for (Express item : expressPaging.getItems()) {
                SuccessVo<User> userSuccessVo = userClient.selectOne(Long.parseLong(item.getUid() + ""));
                if (userSuccessVo.getData() != null) {
                    item.setAvatar(userSuccessVo.getData().getAvatar());
                }
            }
            return expressPaging;
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("查询失败");
        }

    }

    @Override
    public Paging<Express> byUniversity(String authorization, Integer page, Integer size) {
        Map<String, String> claim = userClient.getClaim(authorization);
        String universityId = claim.get("universityId");
        SuccessVo<List<Delivery>> vo = deliveryClient.list(Long.parseLong(universityId));
        List<Paging<Express>> pagingList = new ArrayList<>();
        if (vo.getData() != null) {
            for (Delivery datum : vo.getData()) {
                try {
                    SearchRequest request = new SearchRequest(ORDER_NAME);
                    BoolQueryBuilder bool = QueryBuilders.boolQuery();
                    bool.must(QueryBuilders.termQuery("deliveryId", datum.getId()));
                    request.source().query(bool).sort("updateTime", SortOrder.DESC).size(size).from(page);
                    SearchResponse search = client.search(request, RequestOptions.DEFAULT);

                    Paging<Express> expressPaging = EsPage.simplePage(Express.class, search, page, size);
                    for (Express item : expressPaging.getItems()) {
                        SuccessVo<User> userVO = userClient.selectOne(Long.parseLong(item.getUid() + ""));
                        if (userVO.getData() != null) {
                            item.setAvatar(userVO.getData().getAvatar());
                        }
                    }
                    pagingList.add(expressPaging);
                } catch (IOException e) {
                    e.printStackTrace();
                    throw new RuntimeException("express 分页查询失败");
                }
            }
        }
        List<Express> expressList = new ArrayList<>();
        for (Paging<Express> expressPaging : pagingList) {
            for (Express item : expressPaging.getItems()) {
                expressList.add(item);
            }
        }
        return new Paging<Express>(Long.parseLong(size + ""), Long.parseLong(expressList.size() + ""), page, size, expressList);
    }
}